/*
 * Copyright(c) 2022 长沙市希尚网络科技有限公司
 * 注意：本内容仅限于长沙市希尚网络科技有限公司内部传阅，禁止外泄以及用于其他的商业目的
 */

package org.ssssssss.example.configuration;

import com.google.common.collect.Range;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Collectors;
import org.apache.shardingsphere.infra.spi.annotation.SingletonSPI;
import org.apache.shardingsphere.sharding.api.sharding.standard.PreciseShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.RangeShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.StandardShardingAlgorithm;

/**
 * 按月分表算法
 */
@SingletonSPI
public class MonthAlgorithm implements StandardShardingAlgorithm<LocalDateTime> {

    /**
     * 添加使用
     * @param collection
     * @param preciseShardingValue
     * @return
     */
    @Override
    public String doSharding(Collection<String> collection, PreciseShardingValue<LocalDateTime> preciseShardingValue) {
        String tableName=preciseShardingValue.getLogicTableName();
        return tableName+"_"+ buildRangeTime(preciseShardingValue.getValue());
    }


    /**
     * 查询使用
     * @param collection
     * @param rangeShardingValue
     * @return
     */
    @Override
    public Collection<String> doSharding(Collection<String> collection, RangeShardingValue<LocalDateTime> rangeShardingValue) {
        Range<LocalDateTime> range = rangeShardingValue.getValueRange();
        String tableName=rangeShardingValue.getLogicTableName();
        Set<String> collect = buildRangeTime(range.lowerEndpoint(), range.upperEndpoint())
            .stream()
            .map(date -> tableName+"_" + date)
            .collect(Collectors.toCollection(TreeSet::new));
        return collect;
    }





    @Override
    public String getType() {
        return null;
    }


    /**
     * 月度精确分表
     * @param date 日期
     * @return 月份
     */
    public static Integer buildRangeTime(LocalDateTime date) {
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyyMM");
        Integer dateInteger = Integer.valueOf(df.format(date));
        return dateInteger;
    }

    /**
     * 月度范围分表
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @return 月份集合
     */
    public static Set<Integer> buildRangeTime(LocalDateTime startDate, LocalDateTime endDate) {
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyyMM");
        Integer start = Integer.valueOf(df.format(startDate));
        Integer end = Integer.valueOf(df.format(endDate));
        if (end.equals(start)) {
            return Collections.singleton(end);
        }
        Set<Integer> result = new TreeSet<>();
        long between = ChronoUnit.MONTHS.between(startDate, endDate);
        result.add(start);
        result.add(end);
        for (int i = 1; i <= between; i++) {
            result.add(Integer.valueOf(df.format(endDate.minusMonths(i))));
        }
        return result;
    }

}
